{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "350\n",
      "921\n"
     ]
    }
   ],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "def show(name,img,wait = False):\n",
    "    cv2.imshow(name, img)\n",
    "    if (wait):\n",
    "        cv2.waitKey(0)\n",
    "        cv2.destroyAllWindows()\n",
    "        cv2.waitKey(1)\n",
    "\n",
    "def createImage(name,scare=0.2):\n",
    "    img = cv2.imread(name)\n",
    "    return cv2.resize(img,None,fx=scare,fy=scare)\n",
    "    \n",
    "MIN = 10\n",
    "FLANN_INDEX_KDTREE = 0\n",
    "\n",
    "imageLeft = createImage('zuo.jpg') #缩小图像\n",
    "imageRight = createImage('you.jpg') #缩小图像\n",
    "sift = cv2.SIFT_create() #创建sift对象\n",
    "kp1,descrip1 = sift.detectAndCompute(imageLeft,None) #提取特征点\n",
    "kp2,descrip2 = sift.detectAndCompute(imageRight,None) #提取特征点\n",
    "#创建字典\n",
    "indexParams = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) #创建索引\n",
    "searchParams = dict(checks=50) #搜索次数\n",
    "flann=cv2.FlannBasedMatcher(indexParams,searchParams) #创建匹配对象\n",
    "match=flann.knnMatch(descrip1,descrip2,k=2) #匹配\n",
    "good=[]\n",
    "#过滤特征点\n",
    "for i,(m,n) in enumerate(match):\n",
    "    if(m.distance<0.75*n.distance):\n",
    "        good.append(m)\n",
    "\n",
    "# 当筛选后的匹配对大于10时，计算视角变换矩阵\n",
    "if len(good) > MIN:\n",
    "    src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2) # 提取关键点坐标\n",
    "    ano_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)\n",
    "    M,mask = cv2.findHomography(src_pts,ano_pts,cv2.RANSAC,5.0) # 计算视角变换矩阵\n",
    "    warpImg = cv2.warpPerspective(imageRight, np.linalg.inv(M), (imageLeft.shape[1]+imageRight.shape[1], imageRight.shape[0])) # 旋转变换\n",
    "\n",
    "# show('warpImg',warpImg)\n",
    "rows,cols=imageLeft.shape[:2]\n",
    "# print(rows)\n",
    "# print(cols)\n",
    "for col in range(0,cols):\n",
    "    # 开始重叠的最左端\n",
    "    if imageLeft[:, col].any() and warpImg[:, col].any():\n",
    "        left = col\n",
    "        print(left)\n",
    "        break\n",
    "\n",
    "for col in range(cols-1, 0, -1):\n",
    "    #重叠的最右一列\n",
    "    if imageLeft[:, col].any() and warpImg[:, col].any():\n",
    "        right = col\n",
    "        print(right)\n",
    "        break\n",
    "#加权处理\n",
    "# res = np.zeros([rows, cols, 3], np.uint8)\n",
    "# for row in range(0, rows):\n",
    "#     for col in range(0, cols):\n",
    "#         if not imageLeft[row, col].any():  # 如果没有原图，用旋转的填充\n",
    "#             res[row, col] = warpImg[row, col]\n",
    "#         elif not warpImg[row, col].any():\n",
    "#             res[row, col] = imageLeft[row, col]\n",
    "#         # elif warpImg[row, col] == 255:\n",
    "#         #     res[row, col] = imageLeft[row, col]    \n",
    "#         else:\n",
    "#             print( warpImg[row, col] )\n",
    "#             srcImgLen = float(abs(col - left))\n",
    "#             testImgLen = float(abs(col - right))\n",
    "#             alpha = srcImgLen / (srcImgLen + testImgLen)\n",
    "#             res[row, col] = np.clip(imageLeft[row, col] * (1 - alpha) + warpImg[row, col] * alpha, 0, 255)\n",
    "\n",
    "warpImg[0:imageLeft.shape[0], 0:imageLeft.shape[1]]=imageLeft\n",
    "show('res2',warpImg,True)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "import cv2\n",
    " \n",
    "# 读取要拼接的图片\n",
    "# img1 = cv2.imread('image1.jpg')\n",
    "# img2 = cv2.imread('image2.jpg')\n",
    " \n",
    "# 创建拼接器\n",
    "stitcher = cv2.Stitcher_create()\n",
    " \n",
    "# 进行图片拼接\n",
    "(_, pano) = stitcher.stitch((imageRight,imageLeft))\n",
    "# 如果拼接成功，显示结果\n",
    "if _ == cv2.Stitcher_OK:\n",
    "    cv2.imshow('Panorama', pano)\n",
    "    cv2.waitKey(0)\n",
    "    cv2.destroyAllWindows()\n",
    "    cv2.waitKey(1)\n",
    "else:\n",
    "    print(\"Error during stitching.\") "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
